/* CoralCube | Massively Multiplayer Online Role-Playing Game(MMORPG) Emulator.
|* 
|* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
|*               2008-2010 TrinityCore <http://www.trinitycore.org/>
|*               2008-2010 CoralCube <http://www.CoralCube.com/>
|*
|* This program is free software. You can redistribute it and/or modify it under the terms of 
|* the GNU General Public License as published by the Free Software Foundation, either 
|* version 2 of the License.
|*
|* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, 
|* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
|* See the GNU General Public License for more details.
|*
|* You should have received a copy of the GNU General Public License along with this program. 
|* If not, see <http://www.gnu.org/licenses/>.
|*/

#ifndef RIBONCORE_CHAT_H
#define RIBONCORE_CHAT_H

#include "SharedDefines.h"
#include "Player.h"

#include <vector>

class ChatHandler;
class WorldSession;
class WorldObject;
class Creature;
class Player;
class Unit;
struct GameTele;

class ChatCommand
{
public:
    const char *       Name;
    uint32             SecurityLevel;                   // function pointer required correct align (use uint32)
    bool               AllowConsole;
    bool (*Handler)(ChatHandler*, const char* args);
    std::string        Help;
    ChatCommand *      ChildCommands;
};

class ChatHandler
{
public:
    WorldSession * GetSession() { return m_session; }
    explicit ChatHandler(WorldSession* session) : m_session(session) { }
    explicit ChatHandler(Player* player) : m_session(player->GetSession()) { }
    ~ChatHandler() { }

    static void FillMessageData(WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker);

    void FillMessageData(WorldPacket *data, uint8 type, uint32 language, uint64 target_guid, const char* message)
    {
        FillMessageData(data, m_session, type, language, NULL, target_guid, message, NULL);
    }

    void FillSystemMessageData(WorldPacket *data, const char* message)
    {
        FillMessageData(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, 0, message);
    }

    static char* LineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; }

    // function with different implementation for chat/console
    virtual const char *GetCoreString(int32 entry) const;
    virtual void SendSysMessage(const char *str);

    void SendSysMessage(int32     entry);
    void PSendSysMessage(const char *format, ...) ATTR_PRINTF(2,3);
    void PSendSysMessage(int32     entry, ...);
    std::string PGetParseString(int32 entry, ...);

    int ParseCommands(const char* text);

    static ChatCommand* getCommandTable();

    bool isValidChatMessage(const char* msg);
    void SendGlobalSysMessage(const char *str);

    bool hasStringAbbr(const char* name, const char* part);

    // function with different implementation for chat/console
    virtual bool isAvailable(ChatCommand const& cmd) const;
    virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); }
    virtual bool needReportToTarget(Player* chr) const;
    virtual LocaleConstant GetSessionDbcLocale() const;
    virtual int GetSessionDbLocaleIndex() const;

    bool HasLowerSecurity(Player* target, uint64 guid, bool strong = false);
    bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false);

    void SendGlobalGMSysMessage(const char *str);
    Player*   getSelectedPlayer();
    Creature* getSelectedCreature();
    Unit*     getSelectedUnit();
    WorldObject* getSelectedObject();

    char*     extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL);
    char*     extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL);

    // if args have single value then it return in arg2 and arg1 == NULL
    void      extractOptFirstArg(char* args, char** arg1, char** arg2);
    char*     extractQuotedArg(char* args);

    uint32    extractSpellIdFromLink(char* text);
    uint64    extractGuidFromLink(char* text);
    GameTele const* extractGameTeleFromLink(char* text);
    bool GetPlayerGroupAndGUIDByName(const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline = false);
    std::string extractPlayerNameFromLink(char* text);
    // select by arg (name/link) or in-game selection online/offline player
    bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL);

    std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; }
    std::string GetNameLink(Player* chr) const { return playerLink(chr->GetName()); }

    GameObject* GetNearbyGameObject();
    GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry);
    bool HasSentErrorMessage() { return sentErrorMessage;}
    void SetSentErrorMessage(bool val){ sentErrorMessage = val;};
    static bool LoadCommandTable() { return load_command_table;}
    static void SetLoadCommandTable(bool val){ load_command_table = val;};

protected:
    explicit ChatHandler() : m_session(NULL) {}      // for CLI subclass
    static bool SetDataForCommandInTable(ChatCommand *table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand);
    bool ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd);
    bool ShowHelpForCommand(ChatCommand *table, const char* cmd);
    bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd);

    bool HandleAHBotOptionsCommand(const char * args);
    bool HandleNameAnnounceCommand(const char* args);
    bool HandleGMNameAnnounceCommand(const char* args);
    bool HandleGMAnnounceCommand(const char* args);
    bool HandleGMNotifyCommand(const char* args);

    bool HandleBanAccountCommand(const char* args);
    bool HandleBanAccountByCharCommand(const char* args);
    bool HandleBanCharacterCommand(const char* args);
    bool HandleBanIPCommand(const char* args);
    bool HandleBanInfoAccountCommand(const char* args);
    bool HandleBanInfoCharacterCommand(const char* args);
    bool HandleBanInfoIPCommand(const char* args);
    bool HandleBanListAccountCommand(const char* args);
    bool HandleBanListCharacterCommand(const char* args);
    bool HandleBanListIPCommand(const char* args);

    bool HandleCastCommand(const char *args);
    bool HandleCastBackCommand(const char *args);
    bool HandleCastDistCommand(const char *args);
    bool HandleCastSelfCommand(const char *args);
    bool HandleCastTargetCommand(const char *args);

    bool HandleCharacterCustomizeCommand(const char * args);
    bool HandleCharacterChangeFactionCommand(const char * args);
    bool HandleCharacterChangeRaceCommand(const char * args);
    bool HandleCharacterDeletedDeleteCommand(const char* args);
    bool HandleCharacterDeletedListCommand(const char* args);
    bool HandleCharacterDeletedRestoreCommand(const char* args);
    bool HandleCharacterDeletedOldCommand(const char* args);
    bool HandleCharacterEraseCommand(const char* args);
    bool HandleCharacterLevelCommand(const char* args);
    bool HandleCharacterRenameCommand(const char * args);
    bool HandleCharacterReputationCommand(const char* args);
    bool HandleCharacterTitlesCommand(const char* args);

    bool HandleChannelSetOwnership(const char *args);

    bool HandlePossessCommand(const char* args);
    bool HandleUnPossessCommand(const char* args);
    bool HandleBindSightCommand(const char* args);
    bool HandleUnbindSightCommand(const char* args);

    bool HandleGuildCreateCommand(const char* args);
    bool HandleGuildInviteCommand(const char* args);
    bool HandleGuildUninviteCommand(const char* args);
    bool HandleGuildRankCommand(const char* args);
    bool HandleGuildDeleteCommand(const char* args);

    bool HandleInstanceListBindsCommand(const char* args);
    bool HandleInstanceUnbindCommand(const char* args);
    bool HandleInstanceStatsCommand(const char* args);
    bool HandleInstanceSaveDataCommand(const char * args);

    bool HandleListAurasCommand(const char * args);
    bool HandleListCreatureCommand(const char* args);
    bool HandleListItemCommand(const char* args);
    bool HandleListObjectCommand(const char* args);

    bool HandleLookupAreaCommand(const char* args);
    bool HandleLookupCreatureCommand(const char* args);
    bool HandleLookupEventCommand(const char* args);
    bool HandleLookupFactionCommand(const char * args);
    bool HandleLookupItemCommand(const char * args);
    bool HandleLookupItemSetCommand(const char * args);
    bool HandleLookupObjectCommand(const char* args);
    bool HandleLookupPlayerIpCommand(const char* args);
    bool HandleLookupPlayerAccountCommand(const char* args);
    bool HandleLookupPlayerEmailCommand(const char* args);
    bool HandleLookupQuestCommand(const char* args);
    bool HandleLookupSkillCommand(const char* args);
    bool HandleLookupSpellCommand(const char* args);
    bool HandleLookupTaxiNodeCommand(const char * args);
    bool HandleLookupTeleCommand(const char * args);
    bool HandleLookupMapCommand(const char* args);
    bool HandleLookupTitleCommand(const char * args);

    bool HandlePDumpLoadCommand(const char *args);
    bool HandlePDumpWriteCommand(const char *args);

    bool HandleResetAchievementsCommand(const char * args);
    bool HandleResetAllCommand(const char * args);
    bool HandleResetHonorCommand(const char * args);
    bool HandleResetLevelCommand(const char * args);
    bool HandleResetSpellsCommand(const char * args);
    bool HandleResetStatsCommand(const char * args);
    bool HandleResetTalentsCommand(const char * args);

    bool HandleSendItemsCommand(const char* args);
    bool HandleSendMailCommand(const char* args);
    bool HandleSendMessageCommand(const char * args);
    bool HandleSendMoneyCommand(const char* args);

    bool HandleServerCorpsesCommand(const char* args);
    bool HandleServerExitCommand(const char* args);
    bool HandleServerIdleRestartCommand(const char* args);
    bool HandleServerIdleShutDownCommand(const char* args);
    bool HandleServerInfoCommand(const char* args);
    bool HandleServerMotdCommand(const char* args);
    bool HandleServerPLimitCommand(const char* args);
    bool HandleServerRestartCommand(const char* args);
    bool HandleServerSetLogLevelCommand(const char* args);
    bool HandleServerSetMotdCommand(const char* args);
    bool HandleServerShutDownCommand(const char* args);
    bool HandleServerShutDownCancelCommand(const char* args);
    bool HandleServerSetClosedCommand(const char* args);
    bool HandleServerToggleQueryLogging(const char* args);

    bool HandleServerSetLogFileLevelCommand(const char* args);
    bool HandleServerSetDiffTimeCommand(const char* args);

    bool HandleUnBanAccountCommand(const char* args);
    bool HandleUnBanAccountByCharCommand(const char* args);
    bool HandleUnBanCharacterCommand(const char* args);
    bool HandleUnBanIPCommand(const char* args);

    bool HandleHelpCommand(const char* args);
    bool HandleCommandsCommand(const char* args);
    bool HandleStartCommand(const char* args);
    bool HandleDismountCommand(const char* args);
    bool HandleSaveCommand(const char* args);

    bool HandleSummonCommand(const char* args);
    bool HandleAppearCommand(const char* args);
    bool HandleGroupSummonCommand(const char* args);
    bool HandleRecallCommand(const char* args);
    bool HandleAnnounceCommand(const char* args);
    bool HandleNotifyCommand(const char* args);
    bool HandleGPSCommand(const char* args);
    bool HandleTaxiCheatCommand(const char* args);
    bool HandleWhispersCommand(const char* args);

    bool HandleGUIDCommand(const char* args);
    bool HandleItemMoveCommand(const char* args);
    bool HandleDeMorphCommand(const char* args);
    bool HandlePInfoCommand(const char* args);
    bool HandleMuteCommand(const char* args);
    bool HandleUnmuteCommand(const char* args);
    bool HandleMovegensCommand(const char* args);
    bool HandleFreezeCommand(const char *args);
    bool HandleUnFreezeCommand(const char *args);
    bool HandleListFreezeCommand(const char* args);

    bool HandleCooldownCommand(const char* args);
    bool HandleUnLearnCommand(const char* args);
    bool HandleGetDistanceCommand(const char* args);
    bool HandleDieCommand(const char* args);
    bool HandleDamageCommand(const char *args);
    bool HandleReviveCommand(const char* args);
    bool HandleAuraCommand(const char* args);
    bool HandleUnAuraCommand(const char* args);
    bool HandleLinkGraveCommand(const char* args);
    bool HandleNearGraveCommand(const char* args);
    bool HandleActivateObjectCommand(const char* args);
    bool HandleSpawnTransportCommand(const char* args);
    bool HandleExploreCheatCommand(const char* args);
    bool HandleHoverCommand(const char* args);
    bool HandleWaterwalkCommand(const char* args);
    bool HandleLevelUpCommand(const char* args);
    bool HandleShowAreaCommand(const char* args);
    bool HandleHideAreaCommand(const char* args);
    bool HandleAddItemCommand(const char* args);
    bool HandleAddItemSetCommand(const char* args);
    bool HandlePetTpCommand(const char* args);
    bool HandlePetUnlearnCommand(const char* args);
    bool HandlePetLearnCommand(const char* args);
    bool HandleCreatePetCommand(const char* args);

    bool HandleGroupLeaderCommand(const char* args);
    bool HandleGroupDisbandCommand(const char* args);
    bool HandleGroupRemoveCommand(const char* args);

    bool HandleBankCommand(const char* args);
    bool HandleChangeWeather(const char* args);
    bool HandleKickPlayerCommand(const char * args);

    // BattlefieldWG commands
    bool HandleBattlefieldStart(const char* args);
    bool HandleBattlefieldEnd(const char* args);
    bool HandleBattlefieldSwitch(const char* args);
    bool HandleBattlefieldTimer(const char* args);
    bool HandleBattlefieldEnable(const char* args);

    // GM ticket command handlers
    bool HandleGMTicketListCommand(const char* args);
    bool HandleGMTicketListOnlineCommand(const char* args);
    bool HandleGMTicketListClosedCommand(const char* args);
    bool HandleGMTicketListEscalatedCommand(const char* args);
    bool HandleGMTicketGetByIdCommand(const char* args);
    bool HandleGMTicketGetByNameCommand(const char* args);
    bool HandleGMTicketCloseByIdCommand(const char* args);
    bool HandleGMTicketAssignToCommand(const char* args);
    bool HandleGMTicketUnAssignCommand(const char* args);
    bool HandleGMTicketCommentCommand(const char* args);
    bool HandleGMTicketDeleteByIdCommand(const char* args);
    bool HandleGMTicketReloadCommand(const char*);
    bool HandleToggleGMTicketSystem(const char* args);
    bool HandleGMTicketEscalateCommand(const char* args);
    bool HandleGMTicketCompleteCommand(const char* args);
    bool HandleGMTicketResponseAppendCommand(const char* args);
    bool HandleGMTicketResponseAppendLnCommand(const char* args);

    bool HandleMaxSkillCommand(const char* args);
    bool HandleSetSkillCommand(const char* args);
    bool HandleRespawnCommand(const char* args);
    bool HandleComeToMeCommand(const char *args);
    bool HandleCombatStopCommand(const char *args);

    bool HandleFlushArenaPointsCommand(const char *args);
    bool HandlePlayAllCommand(const char* args);
    bool HandleRepairitemsCommand(const char* args);

    bool HandleTempGameObjectCommand(const char* args);

    //! Development Commands

    bool HandleSaveAllCommand(const char* args);

    // Utility methods for commands
    bool LookupPlayerSearchCommand(QueryResult result, int32 limit);
    bool HandleBanListHelper(QueryResult result);
    bool HandleBanHelper(BanMode mode,char const* args);
    bool HandleBanInfoHelper(uint32 accountid, char const* accountname);
    bool HandleUnBanHelper(BanMode mode,char const* args);
    void HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel);
    void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id);

    // Stores informations about a deleted character
    struct DeletedInfo
    {
        uint32      lowguid;                            ///< the low GUID from the character
        std::string name;                               ///< the character name
        uint32      accountId;                          ///< the account id
        std::string accountName;                        ///< the account name
        time_t      deleteDate;                         ///< the date at which the character has been deleted
    };

    typedef std::list<DeletedInfo> DeletedInfoList;
    bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString = "");
    std::string GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end);
    void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList);
    void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo);

private:
    WorldSession * m_session;                           // != NULL for chat command call and NULL for CLI command

    // common global flag
    static bool load_command_table;
    bool sentErrorMessage;
};

class CliHandler : public ChatHandler
{
public:
    typedef void Print(void*, char const*);
    explicit CliHandler(void* callbackArg, Print* zprint) : m_callbackArg(callbackArg), m_print(zprint) { }

    // overwrite functions
    const char *GetCoreString(int32 entry) const;
    bool isAvailable(ChatCommand const& cmd) const;
    void SendSysMessage(const char *str);
    std::string GetNameLink() const;
    bool needReportToTarget(Player* chr) const;
    LocaleConstant GetSessionDbcLocale() const;
    int GetSessionDbLocaleIndex() const;

private:
    void* m_callbackArg;
    Print* m_print;
};

char const *fmtstring(char const *format, ...);

#endif
